

<template>
  <div class="vue-codemirror">
    <textarea ref="textarea" :placeholder="placeholder"></textarea>
    <div style="padding-top:10px; text-align:right">
      <el-button size="mini" icon="el-icon-rank" @click="full" :class="{fullStatus}" type="success">切换全屏</el-button>
    </div>
  </div>
</template>

<script>
import CodeMirror from 'codemirror'
import 'codemirror/lib/codemirror.css'
import 'codemirror/theme/base16-dark.css'
import 'codemirror/mode/css/css.js'
import 'codemirror/mode/xml/xml.js'
import 'codemirror/mode/javascript/javascript.js'
import 'codemirror/mode/htmlmixed/htmlmixed.js'
import 'codemirror/addon/display/fullscreen.js'
import 'codemirror/addon/display/fullscreen.css'

export default {
  name: 'codemirror',
  data() {
    return {
      code: '',
      codemirror: null,
      cminstance: null,
      option: {
        tabSize: 4,
        lineNumbers: true,
        mode: 'htmlmixed',
        theme: 'base16-dark',
        extraKeys: {
          'F11'(cm) {
            cm.setOption('fullScreen', !cm.getOption('fullScreen'))
            console.log(1)
          },
          'Esc'(cm) {
            if (cm.getOption('fullScreen')) cm.setOption('fullScreen', false)
          }
        }
      }
    }
  },
  props: {
    value: String,
    placeholder: {
      type: String,
      default: ''
    },
    options: {
      type: Object
    },
    mode: {
      type: String
    }
  },
  created() {
    if (this.mode) {
      this.option.mode = this.mode
    }
    if (this.value === undefined) {
      this.code = ''
    } else {
      this.code = this.value
    }
  },
  watch: {
    code(newVal) {
      this.handleCodeChange(newVal)
    }
  },
  computed: {
    fullStatus() {
      return this.cminstance && this.cminstance.getOption('fullScreen')
    }
  },
  methods: {
    initialize() {
      const cmOptions = this.JSONo(this.option, this.options)
      this.codemirror = CodeMirror.fromTextArea(this.$refs.textarea, cmOptions)
      this.cminstance = this.codemirror
      this.cminstance.setValue(this.code)
      this.cminstance.on('change', cm => {
        this.code = cm.getValue()
        if (this.$emit) {
          this.$emit('input', this.code)
        }
      })
    },
    destroy() {
      // garbage cleanup
      const element = this.cminstance.doc.cm.getWrapperElement()
      element && element.remove && element.remove()
    },
    handleCodeChange(newVal) {
      if (this.cminstance) {
        const cm_value = this.cminstance.getValue()
        if (newVal !== cm_value) {
          const scrollInfo = this.cminstance.getScrollInfo()
          this.cminstance.setValue(newVal)
          this.content = newVal
          this.cminstance.scrollTo(scrollInfo.left, scrollInfo.top)
        }
      }
    },
    full() {
      this.cminstance.setOption('fullScreen', !this.cminstance.getOption('fullScreen'))
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.initialize()
    })
  },
  beforeDestroy() {
    this.destroy()
  }
}
</script>

<style lang="scss" scoped>
.vue-codemirror {
  line-height: 1.5;
  font-size: 13px;
}
.fullStatus {
  position: fixed;
  top: 10px;
  right: 30px;
  z-index: 10;
}
</style>
